package com.google.code.ptrends.services.implementations;


import java.util.Calendar;
import java.util.Collection;
import org.apache.log4j.Logger;
import com.google.code.ptrends.common.ProcessorBuilder;
import com.google.code.ptrends.common.entities.EventType;
import com.google.code.ptrends.common.entities.Session;
import com.google.code.ptrends.common.entities.SessionEvent;
import com.google.code.ptrends.entities.ETLItem;
import com.google.code.ptrends.entities.SupplierConfiguration;
import com.google.code.ptrends.locators.Locator;
import com.google.code.ptrends.locators.LocatorFactory;
import com.google.code.ptrends.processors.interfaces.ETLProcessor;
import com.google.code.ptrends.services.DataService;
import com.google.code.ptrends.services.SupplierService;

public class ETLService {

	public ETLService(final LocatorFactory locatorFactory,
			final SupplierService supplierService,
			final ProcessorBuilder processorBuilder,
			final DataService dataService) {
		this.locatorFactory = locatorFactory;
		this.supplierService = supplierService;
		this.processorBuilder = processorBuilder;
		this.dataService = dataService;
	}

	public void serve(final int supplierID, Session session) {
		final SupplierConfiguration cfg = supplierService
				.getConfiguration(supplierID);
		SessionEvent supConfEvent = new SessionEvent();
		if (cfg == null) {
			LOG.error(String.format(
					"Error while loading configuration for supplier ID=%s",
					supplierID));
			
			supConfEvent.setName("Getting supplier configuration");
			supConfEvent.setDescription("Configuration is NULL");
			supConfEvent.setStatus(EventType.ERROR);
			session.setState(EventType.ERROR);
			session.addEvent(supConfEvent);
			session.setEndDate(Calendar.getInstance().getTime());
		} else {
			supConfEvent.setName("Getting supplier configuration");
			supConfEvent.setStatus(EventType.OK);
			supConfEvent.setDescription("Configuration is obtained");
			session.addEvent(supConfEvent);
			
			SessionEvent locatorEvent = new SessionEvent();
			
			final Locator locator = locatorFactory.createLocator(cfg);
			if (locator == null) {
				LOG.error(String.format(
						"Error while building locator for supplier ID=%s",
						supplierID));
				locatorEvent.setName("Building locator");
				locatorEvent.setDescription("Error while building locator");
				locatorEvent.setStatus(EventType.ERROR);
				session.setState(EventType.ERROR);
				session.addEvent(locatorEvent);
				session.setEndDate(Calendar.getInstance().getTime());
			} else {
				locatorEvent.setName("Building locator");
				locatorEvent.setDescription("Locator is builded");
				locatorEvent.setStatus(EventType.OK);
				session.addEvent(locatorEvent);
				
				SessionEvent processorEvent = new SessionEvent();
				
				final ETLProcessor processor = processorBuilder.buildProcessor(
						cfg, locator);

				if (processor == null) {
					LOG.error(String
							.format("Error while building processor for supplier ID=%s",
									supplierID));
					processorEvent.setName("Building processor");
					processorEvent.setDescription("Error while building processor");
					processorEvent.setStatus(EventType.ERROR);
					session.setState(EventType.ERROR);
					session.addEvent(processorEvent);
					session.setEndDate(Calendar.getInstance().getTime());
				} else {
					/*
					 * final Collection<ETLItem> transformedItems = transform(
					 * processor, supplierID);
					 */
					processorEvent.setName("Building processor");
					processorEvent.setDescription("Processor is builded");
					processorEvent.setStatus(EventType.OK);
					session.addEvent(processorEvent);
					
					SessionEvent importDataEvent = new SessionEvent();
					
					Collection<ETLItem> transformedItems = null;
					try {
						transformedItems = processor.importData(supplierID);
						importDataEvent.setName("Transform data");
						importDataEvent.setDescription("Data is transformed");
						importDataEvent.setStatus(EventType.OK);
						session.addEvent(importDataEvent);
					} catch (Exception e) {
						LOG.error(
								String.format(
										"Error transforming source data. SupplierID=%s",
										supplierID), e);
						importDataEvent.setName("Transform data");
						importDataEvent.setDescription("Error while transforming data");
						importDataEvent.setStatus(EventType.ERROR);
						session.addEvent(importDataEvent);
						session.setState(EventType.WARNING);
					} finally {
						locator.close();
					}
					dataService.persistData(transformedItems);
					session.setEndDate(Calendar.getInstance().getTime());
				}
			}
		}
	}

	/*
	 * private Collection<ETLItem> transform(final ETLProcessor processor, final
	 * int supplierID) {
	 * 
	 * Collection<ETLItem> items = new ArrayList<ETLItem>();
	 * 
	 * try { items = processor.importData(supplierID); } catch (Exception e) {
	 * LOG.error(String .format("Error transforming source data. SupplierID=%s",
	 * supplierID), e); }
	 * 
	 * return items; }
	 */
	private static final Logger LOG = Logger.getLogger(ETLService.class);

	private final transient LocatorFactory locatorFactory;
	private final transient SupplierService supplierService;
	private final transient ProcessorBuilder processorBuilder;
	private final transient DataService dataService;
}
